package indigo.mybatis.entity;

import static java.util.Objects.requireNonNull;

import java.io.Serializable;
import java.util.Collections;
import java.util.Map;

import org.apache.ibatis.cache.Cache;

import com.google.common.collect.ImmutableMap;

public class CacheMetadata implements Serializable {
	private static final long serialVersionUID = -6517181110624613466L;

	private final Class<? extends Cache> implementation;
	private final Class<? extends Cache> eviction;
	private final Long flushInterval;
	private final Integer size;
	private final boolean readWrite;
	private final boolean blocking;
	private final Map<String, String> properties;

	protected CacheMetadata(Builder builder) {
		this.implementation = builder.getImplementation();
		this.eviction = builder.getEviction();
		this.flushInterval = builder.getFlushInterval();
		this.size = builder.getSize();
		this.readWrite = builder.isReadWrite();
		this.blocking = builder.isBlocking();
		this.properties = builder.getProperties();
	}

	public Class<? extends Cache> getImplementation() {
		return implementation;
	}

	public Class<? extends Cache> getEviction() {
		return eviction;
	}

	public Long getFlushInterval() {
		return flushInterval;
	}

	public Integer getSize() {
		return size;
	}

	public boolean isReadWrite() {
		return readWrite;
	}

	public boolean isBlocking() {
		return blocking;
	}

	public Map<String, String> getProperties() {
		return properties;
	}

	public static class Builder {
		private Class<? extends Cache> implementation;
		private Class<? extends Cache> eviction;
		private Long flushInterval;
		private Integer size;
		private boolean readWrite;
		private boolean blocking;
		private Map<String, String> properties = Collections.emptyMap();

		public CacheMetadata build() {
			requireNonNull(implementation, "implementation cannot be null");
			requireNonNull(eviction, "eviction cannot be null");
			return new CacheMetadata(this);
		}

		public void setImplementation(Class<? extends Cache> implementation) {
			this.implementation = implementation;
		}

		public void setEviction(Class<? extends Cache> eviction) {
			this.eviction = eviction;
		}

		public void setFlushInterval(Long flushInterval) {
			this.flushInterval = flushInterval;
		}

		public void setSize(Integer size) {
			this.size = size;
		}

		public void setReadWrite(boolean readWrite) {
			this.readWrite = readWrite;
		}

		public void setBlocking(boolean blocking) {
			this.blocking = blocking;
		}

		public void setProperties(Map<String, String> properties) {
			this.properties = properties != null ? ImmutableMap.copyOf(properties) : Collections.emptyMap();
		}

		public Class<? extends Cache> getImplementation() {
			return implementation;
		}

		public Class<? extends Cache> getEviction() {
			return eviction;
		}

		public Long getFlushInterval() {
			return flushInterval;
		}

		public Integer getSize() {
			return size;
		}

		public boolean isReadWrite() {
			return readWrite;
		}

		public boolean isBlocking() {
			return blocking;
		}

		public Map<String, String> getProperties() {
			return properties;
		}
	}
}
